﻿using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.DataStruct;
using UtilZ.Dotnet.Ex.Model;

namespace ConAppCore.Test
{
    internal class TestObjectPool
    {
        private static int _perCount = 1000000;
        public static void Test()
        {
            int[] arr = new int[] { 1, 2, 3, 4, 5, 6 };
            var ret1 = arr.SkipLast(2).ToArray();
            var ret2 = arr.TakeLast(2).ToArray();

            //CancellationToken token = CancellationToken.None;

            //long _index = 0L;
            //long index = Interlocked.Increment(ref _index);

            //long index2 = Interlocked.Increment(ref _index);

            //TestBlockingCollection();
            //TestConcurrentBag();
            //TestObjectPool1();
            //TestSingleTypeObjectPool();
            //ObjectPoolT();

            //TestSingleTypeObjectPool2();

            TestSingleTypeObjectPool();
            //TestSingleTypeObjectPool2ParalPer();

            //for (int i = 0; i < 100; i++)
            //{
            //    TestPoolTime();
            //}
        }

        private static void TestPoolTime()
        {
            var pool1 = new ConcurrentBag<ValueTypeFlexibleArray<byte>>();
            var pool2 = new ConcurrentQueue<ValueTypeFlexibleArray<byte>>();
            int count = 1000000;
            var item = new ValueTypeFlexibleArray<byte>(FlexibleArrayMode.Referenced);
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Restart();
            for (int i = 0; i < count; i++)
            {
                pool1.Add(item);
                pool1.TryTake(out item);
            }
            stopwatch.Stop();
            var time1 = stopwatch.Elapsed.TotalMilliseconds;

            stopwatch.Restart();
            for (int i = 0; i < count; i++)
            {
                pool2.Enqueue(item);
                pool2.TryDequeue(out item);
            }
            stopwatch.Stop();
            var time2 = stopwatch.Elapsed.TotalMilliseconds;

            Console.WriteLine($"ConcurrentBag:{time1}ms        ConcurrentQueue:{time2}ms");
        }

        private static void TestSingleTypeObjectPool2ParalPer()
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            string typeNAme = "SingleTypeObjectPoolBlockingCollection";
            //using var pool = new SingleTypeObjectPool2<TestObjectPoolItem>();
            //using var pool = new SingleTypeObjectPoolQueu<TestObjectPoolItem>();
            using var pool = new SingleTypeObjectPoolBlockingCollection<TestObjectPoolItem>();
            for (int i = 0; i < 10; i++)
            {
                pool.Add(new TestObjectPoolItem());
            }

            Task[] tasks = new Task[4];
            long index = 0;
            for (int i = 0; i < tasks.Length; i++)
            {
                tasks[i] = new Task(() =>
                {
                    TestObjectPoolItem item;
                    for (int j = 0; j < 100000000; j++)
                    {
                        if (pool.TryTake(out item))
                        {

                        }
                        else
                        {
                            item = new TestObjectPoolItem();
                            Console.WriteLine($"创建新项:{Interlocked.Increment(ref index)}");
                        }

                        if (pool.Contains(item))
                        {
                            Console.WriteLine($"悲剧了.{item.ToString()}");
                        }
                        else
                        {
                            //
                            pool.Add(item);
                        }

                        //Thread.Sleep(1);
                    }
                });
                tasks[i].Start();
            }
            Task.WaitAll(tasks);

            stopwatch.Stop();
            //Console.WriteLine($"SingleTypeObjectPool2:{stopwatch.Elapsed.TotalMilliseconds}");
            Console.WriteLine($"{typeNAme}:{stopwatch.Elapsed.TotalMilliseconds}");
        }

        private static void TestSingleTypeObjectPool2()
        {
            using SingleTypeObjectPool2<TestObjectPoolItem> pool = new SingleTypeObjectPool2<TestObjectPoolItem>();

            for (int i = 0; i < 3; i++)
            {
                pool.Add(new TestObjectPoolItem());
            }

            TestObjectPoolItem item;
            long index = 0;
            for (int j = 0; j < _perCount; j++)
            {
                if (pool.TryTake(out item))
                {

                }
                else
                {
                    item = new TestObjectPoolItem();
                    Console.WriteLine($"创建新项:{Interlocked.Increment(ref index)}");
                }

                if (pool.Contains(item))
                {
                    Console.WriteLine($"悲剧了.{item.ToString()}");
                }
                else
                {
                    //
                    pool.Add(item);
                }

                //Thread.Sleep(1);
            }

        }

        private static void ObjectPoolT()
        {
            using ObjectPool<ushort> ObjectPool = new ObjectPool<ushort>();
            ObjectPool.TakeTimeoutResolve += (s, e) =>
            {
                if (e.TypeId == 1)
                {
                    e.Value = new TestObjectPoolItem();
                }
            };

            ObjectPool.Add(1, new TestObjectPoolItem());
            var obj = ObjectPool.Take<TestObjectPoolItem>(1);

            var obj2 = ObjectPool.Take<TestObjectPoolItem>(1);

            ObjectPool.Add(1, obj);
        }

        private static void TestSingleTypeObjectPool()
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            using var pool = new SingleTypeObjectPool<TestObjectPoolItem>();

            for (int i = 0; i < 10; i++)
            {
                pool.Add(new TestObjectPoolItem());
            }

            Task[] tasks = new Task[4];
            long index = 0;
            for (int i = 0; i < tasks.Length; i++)
            {
                tasks[i] = new Task(() =>
                {
                    TestObjectPoolItem item;
                    for (int j = 0; j < _perCount; j++)
                    {
                        if (pool.TryTake(out item))
                        {

                        }
                        else
                        {
                            item = new TestObjectPoolItem();
                            Console.WriteLine($"创建新项:{Interlocked.Increment(ref index)}");
                        }

                        if (pool.Contains(item))
                        {
                            Console.WriteLine($"悲剧了.{item.ToString()}");
                        }
                        else
                        {
                            //
                            pool.Add(item);
                        }

                        //Thread.Sleep(1);
                    }
                });
                tasks[i].Start();
            }
            Task.WaitAll(tasks);

            stopwatch.Stop();
            Console.WriteLine($"TestSingleTypeObjectPool:{stopwatch.Elapsed.TotalMilliseconds}");
        }

        private static void TestObjectPool1()
        {
            using ObjectPool ObjectPool = new ObjectPool();

            TestObjectPool obj;
            if (ObjectPool.TryTake<TestObjectPool>(out obj))
            {

            }
            else
            {
                obj = new TestObjectPool();
            }
            ObjectPool.Add(obj);

            if (ObjectPool.TryTake<TestObjectPool>(out obj))
            {

            }
            else
            {

            }
        }

        private static void TestConcurrentBag()
        {
            ConcurrentBag<TestObjectPoolItem> items = new ConcurrentBag<TestObjectPoolItem>();
            //TestObjectPoolItem value;
            //if (items.TryTake(out value))
            //{

            //}
            //else
            //{


            //}

            for (int i = 0; i < 5; i++)
            {
                items.Add(new TestObjectPoolItem());
            }

            //if (items.TryTake(out value))
            //{

            //}
            //else
            //{

            //}

            using var pool = new SingleTypeObjectPool<TestObjectPoolItem>();
            TestObjectPoolItem item;
            for (int i = 0; i < 10000; i++)
            {
                while (true)
                {
                    try
                    {
                        if (pool.TryTake(out item))
                        {
                            if (pool.Contains(item))
                            {

                            }
                            break;
                        }
                        else
                        {
                            pool.Add(new TestObjectPoolItem());
                        }
                    }
                    catch (ArgumentNullException)
                    {
                        continue;
                    }
                }

                pool.Add(item);
            }

            int count0 = items.Count;

            TestObjectPoolItem[] ret1 = items.Take(1).ToArray();
            int count1 = items.Count;

            TestObjectPoolItem[] ret2 = items.Take(10).ToArray();
            int count2 = items.Count;
        }

        private static void TestBlockingCollection()
        {
            //ConcurrentQueue<T> queue = new ConcurrentQueue<T>();
            ////queue.Enqueue();
            //queue.TryDequeue();

            System.Collections.Concurrent.BlockingCollection<string> _blockingCollection = new System.Collections.Concurrent.BlockingCollection<string>();
            string item;
            var millisecondsTimeout = 10000;
            if (_blockingCollection.TryTake(out item, millisecondsTimeout, CancellationToken.None))
            {

            }
            else
            {

            }
        }

    }

    internal class TestObjectPoolItem
    {
        private static int _id = 1;

        public int ID { get; set; }

        public string Name { get; set; }

        public TestObjectPoolItem()
        {
            this.ID = Interlocked.Increment(ref _id);
            this.Name = $"name:{this.ID}";
        }

        public override string ToString()
        {
            return $"{this.ID}      {this.Name}";
        }
    }






    unsafe internal class SingleTypeObjectPool2<T> : ObjectPoolAbs<T>, IEnumerable<T>
    {
        private const int _DEFAULT_CAPCITY = 100;
        private readonly object _syncRoot = new object();
        private readonly T _defaultValue = default(T);
        private T[] _arr;
        private int _index = 0;
        private int _count = 0;

        /// <summary>
        /// 获取项数
        /// </summary>
        public int Count
        {
            get
            {
                return this._count;
            }
        }






        /// <summary>
        /// 构造函数初始化
        /// </summary>
        /// <param name="capcity">初始化容量</param>
        /// <exception cref="AccessViolationException">初始化失败异常</exception>
        public SingleTypeObjectPool2(int capcity)
           : base()
        {
            this._arr = new T[capcity];
        }

        /// <summary>
        /// 构造函数初始化
        /// </summary>
        public SingleTypeObjectPool2()
            : this(_DEFAULT_CAPCITY)
        {

        }

        /// <summary>
        /// 构造函数初始化
        /// </summary>
        /// <param name="collection">初始对象集合</param>
        public SingleTypeObjectPool2(IEnumerable<T> collection)
            : this(collection == null ? throw new ArgumentNullException(nameof(collection)) : (int)(Math.Ceiling((double)collection.Count() / 10) * 10))
        {
            foreach (T item in collection)
            {
                this._arr[this._index] = item;
                this._index++;
            }
        }






        /// <summary>
        /// 添加对象集合到资源池
        /// </summary>
        /// <param name="collection">复用对象集合</param>
        public void Add(IEnumerable<T> collection)
        {
            if (collection == null)
            {
                return;
            }

            lock (this._syncRoot)
            {
                int count = collection.Count();
                if (this._count + count > this._arr.Length)
                {
                    //扩容
                    this.ExtendCapcity(this._count + count);
                }

                foreach (var item in collection)
                {
                    if (item != null)
                    {
                        this._arr[this._index] = item;
                        this._index++;
                        this._count++;
                    }
                }
            }
        }

        /// <summary>
        /// 添加对象到资源池
        /// </summary>
        /// <param name="item">复用对象</param>
        public void Add(T item)
        {
            if (item == null)
            {
                return;
            }

            lock (this._syncRoot)
            {
                if (this._count >= this._arr.Length)
                {
                    this.ExtendCapcity(this._count + 1);
                }
                this._arr[this._index] = item;
                this._index++;
                this._count++;
            }
        }


        private void ExtendCapcity(long minCapcity)
        {
            double factor;
            if (this._arr.Length < 2000)
            {
                factor = 2D;
            }
            else
            {
                factor = 1.5D;
            }

            long newCapcity = (long)(Math.Ceiling((minCapcity * factor) / 10) * 10);
            T[] arr = new T[newCapcity];
            Array.Copy(this._arr, arr, this._arr.Length);
            this._arr = arr;
        }







        /// <summary>
        /// 获取对象
        /// </summary>
        /// <returns>对象</returns>
        public T Take()
        {
            T item;
            if (this.TryTake(Timeout.Infinite, CancellationToken.None, out item))
            {
                return item;
            }
            else
            {
                throw new Exception("理论上不可能进入此分支.");
            }
        }

        /// <summary>
        /// 获取对象
        /// </summary>
        /// <returns>对象</returns>
        public T Take(CancellationToken token)
        {
            T item;
            if (this.TryTake(Timeout.Infinite, token, out item))
            {
                return item;
            }
            else
            {
                throw new OperationCanceledException();
            }
        }






        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private int GetMillisecondTicks()
        {
            return Environment.TickCount;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private bool CreateItem(out T item)
        {
            object obj;
            if (base.OnRaiseTakeTimeoutResolve(default(T), out obj))
            {
                item = (T)obj;
                return true;
            }
            else
            {
                item = default(T);
                return false;
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private bool PrimitiveTryTake(out T item)
        {
            bool result;

            lock (this._syncRoot)
            {
                if (this._count > 0)
                {
                    int index = this._index - 1;
                    item = this._arr[index];
                    this._arr[index] = this._defaultValue;
                    this._index--;
                    this._count--;
                    result = true;
                }
                else
                {
                    item = this._defaultValue;
                    result = false;
                }
            }

            return result;
        }

        /// <summary>
        /// 尝试获取对象,获取成功返回true,获取失败返回False
        /// </summary>
        /// <param name="item">对象</param>
        /// <returns>获取成功返回true,获取失败返回False</returns>
        public bool TryTake(out T item)
        {
            while (true)
            {
                try
                {
                    if (this.PrimitiveTryTake(out item))
                    {
                        return true;
                    }
                    else
                    {
                        break;
                    }
                }
                catch (ArgumentNullException)
                {
                    //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
                    continue;
                }
            }

            return this.CreateItem(out item);
        }

        /// <summary>
        /// 尝试获取对象,获取成功返回true,获取失败返回False
        /// </summary>
        /// <param name="millisecondsTimeout">超时时长,为Timeout.Infinite时无限</param>
        /// <param name="item">对象</param>
        /// <returns>获取成功返回true,获取失败返回False</returns>
        public bool TryTake(int millisecondsTimeout, out T item)
        {
            int startTimestamp = this.GetMillisecondTicks();

            while (true)
            {
                try
                {
                    if (this.PrimitiveTryTake(out item))
                    {
                        return true;
                    }
                    else
                    {
                        if (millisecondsTimeout == Timeout.Infinite)
                        {
                            continue;
                        }

                        if (this.GetMillisecondTicks() - startTimestamp > millisecondsTimeout)
                        {
                            break;
                        }
                    }
                }
                catch (ArgumentNullException)
                {
                    //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
                    continue;
                }
            }

            return this.CreateItem(out item);
        }

        /// <summary>
        /// 尝试获取对象,获取成功返回true,获取失败返回False
        /// </summary>
        /// <param name="token">取消CancellationToken</param>
        /// <param name="item">对象</param>
        /// <returns>获取成功返回true,获取失败返回False</returns>
        public bool TryTake(CancellationToken token, out T item)
        {
            while (!token.IsCancellationRequested)
            {
                try
                {
                    if (this.PrimitiveTryTake(out item))
                    {
                        return true;
                    }
                    else
                    {
                        continue;
                    }
                }
                catch (ArgumentNullException)
                {
                    //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
                    continue;
                }
            }

            if (token.IsCancellationRequested)
            {
                item = this._defaultValue;
                return false;
            }
            else
            {
                return this.CreateItem(out item);
            }
        }

        /// <summary>
        /// 尝试获取对象,获取成功返回true,获取失败返回False
        /// </summary>
        /// <param name="millisecondsTimeout">超时时长,为Timeout.Infinite时无限</param>
        /// <param name="token">取消CancellationToken</param>
        /// <param name="item">对象</param>
        /// <returns>获取成功返回true,获取失败返回False</returns>
        public bool TryTake(int millisecondsTimeout, CancellationToken token, out T item)
        {
            int startTimestamp = this.GetMillisecondTicks();

            while (!token.IsCancellationRequested)
            {
                try
                {
                    if (this.PrimitiveTryTake(out item))
                    {
                        return true;
                    }
                    else
                    {
                        if (millisecondsTimeout == Timeout.Infinite)
                        {
                            continue;
                        }

                        if (this.GetMillisecondTicks() - startTimestamp > millisecondsTimeout)
                        {
                            break;
                        }
                    }
                }
                catch (ArgumentNullException)
                {
                    //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
                    continue;
                }
            }

            if (token.IsCancellationRequested)
            {
                item = default(T);
                return false;
            }
            else
            {
                return this.CreateItem(out item);
            }
        }





        /// <summary>
        /// 移除指定项的项,如果真实项数小于了要移除的项数,则全部移除
        /// </summary>
        /// <param name="count">要移除的项数</param>
        /// <returns>移除项列表</returns>
        public List<T> Remove(int count)
        {
            if (count <= 0)
            {
                return null;
            }

            List<T> list;
            lock (this._syncRoot)
            {
                if (this._count > count)
                {
                    list = new List<T>(this._arr.Take(count));
                    Array.Fill(this._arr, this._defaultValue, this._index - count, count);
                    this._index -= count;
                    this._count -= count;
                }
                else
                {
                    list = new List<T>(this._arr);
                    Array.Fill(this._arr, this._defaultValue);
                    this._index = 0;
                    this._count = 0;
                }
            }

            return list;
        }

        /// <summary>
        /// 清空集合,并返回清空项列表
        /// </summary>
        /// <returns>清空项列表</returns>
        public List<T> Clear()
        {
            List<T> list;
            lock (this._syncRoot)
            {
                list = new List<T>(this._arr.Take(this._count));
                Array.Fill(this._arr, this._defaultValue);
                this._index = 0;
                this._count = 0;
            }
            return list;
        }

        /// <summary>
        /// 判断当前集合是否包含指定项.包含返回true,不包含返回false
        /// </summary>
        /// <param name="item">指定项</param>
        /// <returns>包含返回true,不包含返回false</returns>
        public bool Contains(T item)
        {
            if (item == null)
            {
                return false;
            }

            bool result = false;
            lock (this._syncRoot)
            {
                for (int i = 0; i < this._index; i++)
                {
                    if (object.ReferenceEquals(this._arr[this._index], item) || object.Equals(this._arr[this._index], item))
                    {
                        result = true;
                        break;
                    }
                }
            }
            return result;
        }



        /// <summary>
        /// ToArray
        /// </summary>
        /// <returns>新的数组</returns>
        public T[] ToArray()
        {
            T[] arr;
            lock (this._syncRoot)
            {
                arr = new T[this._count];
                Array.Copy(this._arr, 0, arr, 0, this._count);
            }
            return arr;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {

        }





        /// 
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public IEnumerator<T> GetEnumerator()
        {
            return new SingleTypeObjectPoolEnumerator(this);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        /// <summary>
        /// 单类型对象池
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        private class SingleTypeObjectPoolEnumerator : IEnumerator<T>
        {
            private readonly SingleTypeObjectPool2<T> _innerPool;
            private int _enumeratorIndex = -1;
            private T _current;


            public SingleTypeObjectPoolEnumerator(SingleTypeObjectPool2<T> innerPool)
            {
                this._innerPool = innerPool;
                this._current = innerPool._defaultValue;
            }


            public T Current
            {
                get { return this._current; }
            }

            object IEnumerator.Current
            {
                get { return this._current; }
            }



            public bool MoveNext()
            {
                bool result;
                this._enumeratorIndex++;

                lock (this._innerPool._syncRoot)
                {
                    if (this._enumeratorIndex < this._innerPool._count)
                    {
                        this._current = this._innerPool._arr[this._enumeratorIndex];
                        result = true;
                    }
                    else
                    {
                        this._current = this._innerPool._defaultValue;
                        result = false;

                    }
                }
                return result;
            }

            public void Reset()
            {
                this._enumeratorIndex = -1;
            }

            public void Dispose()
            {

            }
        }



    }


    /// <summary>
    /// 单类型对象池
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    internal class SingleTypeObjectPoolQueue<T> : ObjectPoolAbs<T>, IEnumerable<T>
    {
        private readonly ConcurrentQueue<T> _items;

        /// <summary>
        /// 获取项数
        /// </summary>
        public int Count
        {
            get { return _items.Count; }
        }




        /// <summary>
        /// 构造函数初始化
        /// </summary>
        public SingleTypeObjectPoolQueue()
            : base()
        {
            this._items = new ConcurrentQueue<T>();
        }

        /// <summary>
        /// 构造函数初始化
        /// </summary>
        /// <param name="collection">初始对象集合</param>
        public SingleTypeObjectPoolQueue(IEnumerable<T> collection)
            : base()
        {
            if (collection == null || collection.Count() == 0)
            {
                this._items = new ConcurrentQueue<T>();
            }
            else
            {
                this._items = new ConcurrentQueue<T>(collection);
            }
        }






        /// <summary>
        /// 添加对象集合到资源池
        /// </summary>
        /// <param name="collection">复用对象集合</param>
        public void Add(IEnumerable<T> collection)
        {
            if (collection == null)
            {
                return;
            }

            foreach (var item in collection)
            {
                if (item != null)
                {
                    this._items.Enqueue(item);
                }
            }
        }

        /// <summary>
        /// 添加对象到资源池
        /// </summary>
        /// <param name="item">复用对象</param>
        public void Add(T item)
        {
            if (item != null)
            {
                this._items.Enqueue(item);
            }
        }






        /// <summary>
        /// 获取对象
        /// </summary>
        /// <returns>对象</returns>
        public T Take()
        {
            T item;
            if (this.TryTake(Timeout.Infinite, CancellationToken.None, out item))
            {
                return item;
            }
            else
            {
                throw new Exception("理论上不可能进入此分支.");
            }
        }

        /// <summary>
        /// 获取对象
        /// </summary>
        /// <returns>对象</returns>
        public T Take(CancellationToken token)
        {
            T item;
            if (this.TryTake(Timeout.Infinite, token, out item))
            {
                return item;
            }
            else
            {
                throw new OperationCanceledException();
            }
        }






        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private int GetMillisecondTicks()
        {
            return Environment.TickCount;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private bool CreateItem(out T item)
        {
            object obj;
            if (base.OnRaiseTakeTimeoutResolve(default(T), out obj))
            {
                item = (T)obj;
                return true;
            }
            else
            {
                item = default(T);
                return false;
            }
        }

        /// <summary>
        /// 尝试获取对象,获取成功返回true,获取失败返回False
        /// </summary>
        /// <param name="item">对象</param>
        /// <returns>获取成功返回true,获取失败返回False</returns>
        public bool TryTake(out T item)
        {
            while (true)
            {
                try
                {
                    if (this._items.TryDequeue(out item))
                    {
                        return true;
                    }
                    else
                    {
                        break;
                    }
                }
                catch (ArgumentNullException)
                {
                    //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
                    continue;
                }
            }

            return this.CreateItem(out item);
        }

        /// <summary>
        /// 尝试获取对象,获取成功返回true,获取失败返回False
        /// </summary>
        /// <param name="millisecondsTimeout">超时时长,为Timeout.Infinite时无限</param>
        /// <param name="item">对象</param>
        /// <returns>获取成功返回true,获取失败返回False</returns>
        public bool TryTake(int millisecondsTimeout, out T item)
        {
            int startTimestamp = this.GetMillisecondTicks();

            while (true)
            {
                try
                {
                    if (this._items.TryDequeue(out item))
                    {
                        return true;
                    }
                    else
                    {
                        if (millisecondsTimeout == Timeout.Infinite)
                        {
                            continue;
                        }

                        if (this.GetMillisecondTicks() - startTimestamp > millisecondsTimeout)
                        {
                            break;
                        }
                    }
                }
                catch (ArgumentNullException)
                {
                    //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
                    continue;
                }
            }

            return this.CreateItem(out item);
        }

        ///// <summary>
        ///// 尝试获取对象,获取成功返回true,获取失败返回False
        ///// </summary>
        ///// <param name="token">取消CancellationToken</param>
        ///// <param name="item">对象</param>
        ///// <returns>获取成功返回true,获取失败返回False</returns>
        //public bool TryTake(CancellationToken token, out T item)
        //{
        //    while (!token.IsCancellationRequested)
        //    {
        //        try
        //        {
        //            if (this._items.TryTake(out item))
        //            {
        //                return true;
        //            }
        //            else
        //            {
        //                continue;
        //            }
        //        }
        //        catch (ArgumentNullException)
        //        {
        //            //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
        //            continue;
        //        }
        //    }

        //    if (token.IsCancellationRequested)
        //    {
        //        item = default(T);
        //        return false;
        //    }
        //    else
        //    {
        //        return this.CreateItem(out item);
        //    }
        //}

        /// <summary>
        /// 尝试获取对象,获取成功返回true,获取失败返回False
        /// </summary>
        /// <param name="millisecondsTimeout">超时时长,为Timeout.Infinite时无限</param>
        /// <param name="token">取消CancellationToken</param>
        /// <param name="item">对象</param>
        /// <returns>获取成功返回true,获取失败返回False</returns>
        public bool TryTake(int millisecondsTimeout, CancellationToken token, out T item)
        {
            int startTimestamp = this.GetMillisecondTicks();

            while (!token.IsCancellationRequested)
            {
                try
                {
                    if (this._items.TryDequeue(out item))
                    {
                        return true;
                    }
                    else
                    {
                        if (millisecondsTimeout == Timeout.Infinite)
                        {
                            continue;
                        }

                        if (this.GetMillisecondTicks() - startTimestamp > millisecondsTimeout)
                        {
                            break;
                        }
                    }
                }
                catch (ArgumentNullException)
                {
                    //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
                    continue;
                }
            }

            if (token.IsCancellationRequested)
            {
                item = default(T);
                return false;
            }
            else
            {
                return this.CreateItem(out item);
            }
        }





        /// <summary>
        /// 移除指定项的项,如果真实项数小于了要移除的项数,则全部移除
        /// </summary>
        /// <param name="count">要移除的项数</param>
        /// <returns>移除项列表</returns>
        public List<T> Remove(int count)
        {
            if (count <= 0)
            {
                return null;
            }

            List<T> list = null;
            T item;

            while (true)
            {
                if (this.TryTake(out item))
                {
                    if (list == null)
                    {
                        list = new List<T>();
                    }

                    list.Add(item);
                    if (list.Count >= count)
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }
            }

            return list;
        }

        /// <summary>
        /// 清空集合,并返回清空项列表
        /// </summary>
        /// <returns>清空项列表</returns>
        public List<T> Clear()
        {
            List<T> list = null;
            T item;

            while (true)
            {
                try
                {
                    if (this.TryTake(out item))
                    {
                        if (list == null)
                        {
                            list = new List<T>();
                        }

                        list.Add(item);
                    }
                    else
                    {
                        break;
                    }
                }
                catch (ArgumentNullException)
                {
                    continue;
                }
            }

            return list;
        }

        /// <summary>
        /// 判断当前集合是否包含指定项.包含返回true,不包含返回false
        /// </summary>
        /// <param name="item">指定项</param>
        /// <returns>包含返回true,不包含返回false</returns>
        public bool Contains(T item)
        {
            if (item == null)
            {
                return false;
            }

            return this._items.Contains(item);
        }




        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public IEnumerator<T> GetEnumerator()
        {
            return this._items.GetEnumerator();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this._items.GetEnumerator();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {

        }

    }


    /// <summary>
    /// 单类型对象池
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    internal class SingleTypeObjectPoolBlockingCollection<T> : ObjectPoolAbs<T>
    {
        private readonly BlockingCollection<T> _items;

        /// <summary>
        /// 获取项数
        /// </summary>
        public int Count
        {
            get { return _items.Count; }
        }




        /// <summary>
        /// 构造函数初始化
        /// </summary>
        public SingleTypeObjectPoolBlockingCollection()
            : base()
        {
            this._items = new BlockingCollection<T>();
        }

        /// <summary>
        /// 构造函数初始化
        /// </summary>
        /// <param name="collection">初始对象集合</param>
        public SingleTypeObjectPoolBlockingCollection(IEnumerable<T> collection)
            : base()
        {
            if (collection == null || collection.Count() == 0)
            {
                this._items = new BlockingCollection<T>();
            }
            else
            {
                this._items = new BlockingCollection<T>();

                foreach (var item in collection)
                {
                    this._items.Add(item);
                }
            }
        }






        /// <summary>
        /// 添加对象集合到资源池
        /// </summary>
        /// <param name="collection">复用对象集合</param>
        public void Add(IEnumerable<T> collection)
        {
            if (collection == null)
            {
                return;
            }

            foreach (var item in collection)
            {
                if (item != null)
                {
                    this._items.Add(item);
                }
            }
        }

        /// <summary>
        /// 添加对象到资源池
        /// </summary>
        /// <param name="item">复用对象</param>
        public void Add(T item)
        {
            if (item != null)
            {
                this._items.Add(item);
            }
        }






        /// <summary>
        /// 获取对象
        /// </summary>
        /// <returns>对象</returns>
        public T Take()
        {
            T item;
            if (this.TryTake(Timeout.Infinite, CancellationToken.None, out item))
            {
                return item;
            }
            else
            {
                throw new Exception("理论上不可能进入此分支.");
            }
        }

        /// <summary>
        /// 获取对象
        /// </summary>
        /// <returns>对象</returns>
        public T Take(CancellationToken token)
        {
            T item;
            if (this.TryTake(Timeout.Infinite, token, out item))
            {
                return item;
            }
            else
            {
                throw new OperationCanceledException();
            }
        }







        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private bool CreateItem(out T item)
        {
            object obj;
            if (base.OnRaiseTakeTimeoutResolve(default(T), out obj))
            {
                item = (T)obj;
                return true;
            }
            else
            {
                item = default(T);
                return false;
            }
        }

        /// <summary>
        /// 尝试获取对象,获取成功返回true,获取失败返回False
        /// </summary>
        /// <param name="item">对象</param>
        /// <returns>获取成功返回true,获取失败返回False</returns>
        public bool TryTake(out T item)
        {
            while (true)
            {
                try
                {
                    if (this._items.TryTake(out item))
                    {
                        return true;
                    }
                    else
                    {
                        break;
                    }
                }
                catch (ArgumentNullException)
                {
                    //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
                    continue;
                }
            }

            return this.CreateItem(out item);
        }

        /// <summary>
        /// 尝试获取对象,获取成功返回true,获取失败返回False
        /// </summary>
        /// <param name="millisecondsTimeout">超时时长,为Timeout.Infinite时无限</param>
        /// <param name="item">对象</param>
        /// <returns>获取成功返回true,获取失败返回False</returns>
        public bool TryTake(int millisecondsTimeout, out T item)
        {
            while (true)
            {
                try
                {
                    return this._items.TryTake(out item, millisecondsTimeout);
                }
                catch (ArgumentNullException)
                {
                    //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
                    continue;
                }
            }
        }



        /// <summary>
        /// 尝试获取对象,获取成功返回true,获取失败返回False
        /// </summary>
        /// <param name="millisecondsTimeout">超时时长,为Timeout.Infinite时无限</param>
        /// <param name="token">取消CancellationToken</param>
        /// <param name="item">对象</param>
        /// <returns>获取成功返回true,获取失败返回False</returns>
        public bool TryTake(int millisecondsTimeout, CancellationToken token, out T item)
        {
            while (!token.IsCancellationRequested)
            {
                try
                {
                    return this._items.TryTake(out item, millisecondsTimeout, token);
                }
                catch (ArgumentNullException)
                {
                    //ConcurrentBag<T>.TryTake偶尔会报ArgumentNullException异常,所以此处采用这种比较怪异的规避异常写法
                    continue;
                }
            }

            if (token.IsCancellationRequested)
            {
                item = default(T);
                return false;
            }
            else
            {
                return this.CreateItem(out item);
            }
        }





        /// <summary>
        /// 移除指定项的项,如果真实项数小于了要移除的项数,则全部移除
        /// </summary>
        /// <param name="count">要移除的项数</param>
        /// <returns>移除项列表</returns>
        public List<T> Remove(int count)
        {
            if (count <= 0)
            {
                return null;
            }

            List<T> list = null;
            T item;

            while (true)
            {
                if (this.TryTake(out item))
                {
                    if (list == null)
                    {
                        list = new List<T>();
                    }

                    list.Add(item);
                    if (list.Count >= count)
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }
            }

            return list;
        }

        /// <summary>
        /// 清空集合,并返回清空项列表
        /// </summary>
        /// <returns>清空项列表</returns>
        public List<T> Clear()
        {
            List<T> list = null;
            T item;

            while (true)
            {
                try
                {
                    if (this.TryTake(out item))
                    {
                        if (list == null)
                        {
                            list = new List<T>();
                        }

                        list.Add(item);
                    }
                    else
                    {
                        break;
                    }
                }
                catch (ArgumentNullException)
                {
                    continue;
                }
            }

            return list;
        }

        /// <summary>
        /// 判断当前集合是否包含指定项.包含返回true,不包含返回false
        /// </summary>
        /// <param name="item">指定项</param>
        /// <returns>包含返回true,不包含返回false</returns>
        public bool Contains(T item)
        {
            if (item == null)
            {
                return false;
            }

            return this._items.Contains(item);
        }




        /// <summary>
        /// 
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {

        }

    }

}

